承接上一篇分享,列表資料完成雛型之後,接著是建立分頁碼與列表連動。
分頁碼使用 Bootstrap 樣式,再作了小修改以呈現出 5 種按鈕(第一頁、上一頁、中間分頁碼、下一頁、最後一頁)。
Bootstrap 分頁樣式
Kuick 分頁樣式
Kuick 提供 Paginator 類別協助建立所需要的分頁參數,Paginator 建構式只需傳入「每頁資料筆數」、「目前資料頁碼」與「所有資料筆數」,就可以取得以下分頁參數:
public int Count { get; } // 資料筆數
public int FirstPageIndex { get; } // 第一頁頁碼
public int LastPageIndex { get; } // 最後一頁頁碼
public int NextPageIndex { get; } // 下一頁頁碼
public int NextViewPortPageIndex { get; } // 下一頁區間頁碼
public int PageIndex { get; } // 目前頁碼
public int PageRowCount { get; } // 本頁資料筆數
public PageOne[] Pages { get; } // 區間頁碼集合
public int PageSize { get; } // 分頁資料筆數
public int PrePageIndex { get; } // 前一頁頁碼
public int PreViewPortPageIndex { get; } // 上一頁區間頁碼
public int RowFrom { get; } // 本頁起始資料序次
public int RowTo { get; } // 本頁結束資料序次
public int ViewportSize { get; set; } // 區間頁數
列表資料額外在所產生的 HTML 裡,加上幾個自定義的 attribute,這些資料將用於後續 Ajax 處理的參數來源:
1. table >> EntityName
table 加上 EntityName 屬性,載明資料來源。
2. tr >> KeyValue
每一筆資料 tr 加上 KeyValue 屬性,載明該筆資料主鍵。
3. td >> ColumnName
每一個欄位 td 加上 ColumnName 屬性,載明資料欄位名稱。
接下來直接將列表頁程式碼貼上,完整的範例網站將於10/30提供下載。
using System;
using System.Collections.Generic;
using System.Text;
using Kuick;
using Kuick.Data;
using Kuick.Labs.IronMan6;
using Kuick.Web;
public partial class entity_default : PageBase
{
[RequestParameter]
public string EntityName { get; set; }
[RequestParameter]
public int PageSize { get; set; }
[RequestParameter]
public int PageIndex { get; set; }
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
PageSize = 2;
PageIndex = Math.Max(PageIndex, 1);
}
// 顯示列表與分頁
public string Render()
{
// 規格驗證
IEntity schema = null;
try {
schema = EntityCache.Get(EntityName);
if(null == schema) { return string.Empty; }
} catch(Exception ex) {
Logger.Error(ex, new Any("EntityName", EntityName));
Response.Redirect("~/", true);
}
StringBuilder sb = new StringBuilder();
BuildList(sb, schema);
BuildPaginator(sb);
return sb.ToString();
}
// 建立列表資料
public void BuildList(StringBuilder sb, IEntity schema)
{
// 選取分頁資料集合
List<IEntity> instances = BuildSql().Query();
// table open tag
sb.AppendFormat(
"<table class=\"table table-bordered table-hover\" EntityName=\"{0}\">",
EntityName
);
// thead
sb.Append("<thead>");
sb.Append("<tr>");
sb.Append("<th class=\"ellipsis\">#</th>");
foreach(var column in schema.Columns) {
if(SkipField(column)) { continue; }
sb.AppendFormat("<th class=\"ellipsis\">{0}</th>", column.Title);
}
sb.Append("</tr>");
sb.Append("</thead>");
// tbody
int index = PageSize * (PageIndex - 1);
sb.Append("<tbody>");
if(instances.IsNullOrEmpty()) {
sb.Append("<tr>");
sb.AppendFormat(
"<td colspan=\"{0}\">-- no data --</td>",
DisplayFieldCount(schema) + 1
);
sb.Append("</tr>");
} else {
foreach(var instance in instances) {
sb.AppendFormat("<tr KeyValue=\"{0}\">", instance.KeyValue);
sb.AppendFormat("<td class=\"ellipsis\">{0}</td>", ++index);
foreach(var column in schema.Columns) {
if(SkipField(column)) { continue; }
sb.AppendFormat(
"<td class=\"ellipsis\" ColumnName=\"{0}\">{1}</td>",
column.Spec.ColumnName,
DisplayFieldValue(instance, column)
);
}
sb.Append("</tr>");
}
}
sb.Append("</tbody>");
// table close tag
sb.Append("</table>");
}
// 建立分頁資料
public void BuildPaginator(StringBuilder sb)
{
Paginator paginator = new Paginator(
PageSize, PageIndex, BuildSql().Count()
);
Anys parameters = new Anys();
parameters.Add(IronMan6Constants.EntityName, EntityName);
string url = WebTools.GetCurrentFullPath();
Anys ps = new Anys();
paginator.ViewportSize = 10;
Anys anys = new Anys();
if(!Checker.IsNull(parameters)) {
anys.AddRange(parameters);
}
// PageSize
if(!anys.Exists(IronMan6Constants.PageSize)) {
anys.Add(new Any(
IronMan6Constants.PageSize,
paginator.PageSize
));
}
// PageIndex
anys.Remove(IronMan6Constants.PageIndex);
sb.Append("<div class=\"text-center\">");
sb.Append("<ul class=\"pagination\">");
// FirstPage
bool disabledFirst = PageIndex < 2;
ps = BuildPaginatorParameter(anys, paginator.FirstPageIndex);
sb.AppendFormat(
"<li{0}><a href=\"{1}\">«</a></li>",
disabledFirst ? " class=\"disabled\"" : string.Empty,
WebTools.BuildQueryString(url, ps.ToArray())
);
// PrePageIndex
bool disabledPre = PageIndex < 2;
ps = BuildPaginatorParameter(anys, paginator.PrePageIndex);
sb.AppendFormat(
"<li{0}><a href=\"{1}\"><</a></li>",
disabledPre ? " class=\"disabled\"" : string.Empty,
WebTools.BuildQueryString(url, ps.ToArray())
);
// Viewport
foreach(PageOne page in paginator.Pages) {
bool active = page.PageIndex == paginator.PageIndex;
ps = BuildPaginatorParameter(anys, page.PageIndex);
sb.AppendFormat(
"<li{0}><a href=\"{1}\">{2}</a></li>",
active ? " class=\"active\"" : string.Empty,
WebTools.BuildQueryString(url, ps.ToArray()),
page.PageIndex
);
}
// NextPageIndex
bool disabledNext = PageIndex >= paginator.LastPageIndex;
ps = BuildPaginatorParameter(anys, paginator.NextPageIndex);
sb.AppendFormat(
"<li{0}><a href=\"{1}\">></a>",
disabledNext ? " class=\"disabled\"" : string.Empty,
WebTools.BuildQueryString(url, ps.ToArray())
);
// LastPageIndex
bool disabledLast = PageIndex >= paginator.LastPageIndex;
ps = BuildPaginatorParameter(anys, paginator.LastPageIndex);
sb.AppendFormat(
"<li{0}><a href=\"{1}\">»</a>",
disabledLast ? " class=\"disabled\"" : string.Empty,
WebTools.BuildQueryString(url, ps.ToArray())
);
sb.Append("</ul>");
sb.Append("</div>");
}
// 建立分頁參數
private Anys BuildPaginatorParameter(Anys ps, int index)
{
Anys anys = new Anys(ps.ToArray());
anys.Add(new Any(IronMan6Constants.PageIndex, index));
return anys;
}
// 建立查詢Sql物件
private Sql BuildSql()
{
Sql sql = Entity
.Sql(EntityName)
.Paging(PageSize, PageIndex);
return sql;
}
// 顯示欄位數目
private int DisplayFieldCount(IEntity schema)
{
int count = 0;
foreach(var column in schema.Columns) {
if(!SkipField(column)) { count++; }
}
return count;
}
// 隱藏欄位判斷
private bool SkipField(Column column)
{
// 加密欄位
if(null != column.Encryption) { return true; }
// 系統內建欄位
if(column.Visual.SystemColumn) { return true; }
// 其他欄位皆顯示
return false;
}
// 重組欄位值
private string DisplayFieldValue(IEntity instance, Column column)
{
// null 欄位直接回傳空定串
bool isNull = instance.IsNullCheck(column.Spec.ColumnName);
if(isNull) { return string.Empty; }
// 取值
object value = instance.GetValue(column);
if(
null != column.Refer.Type
&&
column.Spec.DbType != SqlDataType.Enum
&&
column.Spec.DbType != SqlDataType.Bit) {
// 以 PK 參照其他 Entity
// 從 Entity 快取取出參照定義
IEntity[] refSchemas = EntityCache.Get(column.Refer.Type);
if(refSchemas.IsNullOrEmpty()) {
return string.Empty;
} else {
IEntity one = Entity.Get(
refSchemas[0].EntityName,
value.ToString()
);
if(null == one) {
return value.ToString();
} else {
// 回傳參照資料 TitleValue 屬性
return one.TitleValue;
}
}
} else if(column.IsBoolean) {
// 布林值:使用圖型顯示
bool b = (bool)value;
return b
? "<span class=\"glyphicon glyphicon-ok\"></span>"
: string.Empty;
} else if(column.IsNumber) {
// 數值
return value.ToString();
} else if(column.IsDateTime) {
// 日期
DateTime d = (DateTime)value;
if(column.Visual.Input == VisualInput.Date) {
// 只顯示年月日 (yyyy-MM-dd)
return d.yyyyMMdd();
} else {
// 顯示時戳 (yyyy-MM-dd hh:mm:ss)
return d.yyyyMMddHHmmss();
}
} else if(column.IsEnum) {
// 列舉
// 從列舉快取取出定義
EnumReference ef = EnumCache.Get(column.Property.PropertyType);
if(null == ef) { return string.Empty; }
// 查詢目前列舉項目資訊
EnumItem ei = ef.Get(value.ToString());
if(null == ei) { return string.Empty; }
// 顯示該列舉項目 DescriptionAttribute 定義值
return ei.Title;
} else {
// 一般
return value.ToString();
}
}
}